home *** CD-ROM | disk | FTP | other *** search
/ Workbench Add-On / Workbench Add-On - Volume 1.iso / BBS-Archive / Comm / AmiTCP30b2.lha / src / amitcp / netinet / ip_icmp.c < prev    next >
C/C++ Source or Header  |  1993-08-12  |  17KB  |  593 lines

  1. RCS_ID_C="$Id: ip_icmp.c,v 1.14 1993/06/04 11:16:15 jraja Exp $";
  2. /*
  3.  * Copyright (c) 1993 AmiTCP/IP Group, <amitcp-group@hut.fi>,
  4.  *                    Helsinki University of Technology, Finland.
  5.  *                    All rights reserved.
  6.  *
  7.  * HISTORY
  8.  * $Log: ip_icmp.c,v $
  9.  * Revision 1.14  1993/06/04  11:16:15  jraja
  10.  * Fixes for first public release.
  11.  *
  12.  * Revision 1.13  1993/05/31  23:37:02  jraja
  13.  * made icmpprintfs visible regardless of the ICMPPRINTFS definition.
  14.  *
  15.  * Revision 1.12  1993/05/17  00:16:44  ppessi
  16.  * Changed RCS version. Added rcsid.
  17.  *
  18.  * Revision 1.11  1993/04/11  22:26:41  jraja
  19.  * Added STKARGFUN to protocol input & output functions (if used in protosw).
  20.  *
  21.  * Revision 1.10  93/04/05  19:06:03  19:06:03  jraja (Jarno Tapio Rajahalme)
  22.  * Changed storage of the spl functions  return values to type spl_t.
  23.  * Added include for conf.h to every .c file.
  24.  * 
  25.  * Revision 1.9  93/03/22  16:59:10  16:59:10  jraja (Jarno Tapio Rajahalme)
  26.  * Changed bcopy()s and bzero()s with word aligned pointers to
  27.  * aligned_b(copy|zero) ar aligned_b(copy|zero)_const. The latter is for calls
  28.  * in which the size is constant.
  29.  * These can be disabled by defining NOALIGN.
  30.  *  Converted bcopys doing structure copies (on aligned pointers) to structure
  31.  * assignments, since at least SASC produces better code with assignment.
  32.  * 
  33.  * Revision 1.8  93/03/13  17:14:20  17:14:20  ppessi (Pekka Pessi)
  34.  * Fixed bugs with variable initialization.
  35.  * 
  36.  * Revision 1.7  93/03/05  21:09:36  21:09:36  jraja (Jarno Tapio Rajahalme)
  37.  * Fixed includes (again).
  38.  * 
  39.  * Revision 1.6  93/03/05  03:20:03  03:20:03  ppessi (Pekka Pessi)
  40.  * Compiles with SASC. Initial test version.
  41.  * 
  42.  * Revision 1.5  93/03/04  12:12:34  12:12:34  jraja (Jarno Tapio Rajahalme)
  43.  * Added casts to printf's.
  44.  * 
  45.  * Revision 1.4  93/03/03  22:00:04  22:00:04  jraja (Jarno Tapio Rajahalme)
  46.  * Moved 'icmpstat' definition here from icmp_var.h.
  47.  * 
  48.  * Revision 1.3  93/03/02  18:31:30  18:31:30  too (Tomi Ollila)
  49.  * Changed %? to %l? on format strings
  50.  * 
  51.  * Revision 1.2  93/02/26  09:00:51  09:00:51  jraja (Jarno Tapio Rajahalme)
  52.  * Made this compile with ANSI C (added prototypes).
  53.  * 
  54.  * Revision 1.1  92/11/17  16:29:30  16:29:30  jraja (Jarno Tapio Rajahalme)
  55.  * Initial revision
  56.  *
  57.  */
  58.  
  59. /*
  60.  * Copyright (c) 1982, 1986, 1989 Regents of the University of California.
  61.  * All rights reserved.
  62.  *
  63.  * Redistribution and use in source and binary forms, with or without
  64.  * modification, are permitted provided that the following conditions
  65.  * are met:
  66.  * 1. Redistributions of source code must retain the above copyright
  67.  *    notice, this list of conditions and the following disclaimer.
  68.  * 2. Redistributions in binary form must reproduce the above copyright
  69.  *    notice, this list of conditions and the following disclaimer in the
  70.  *    documentation and/or other materials provided with the distribution.
  71.  * 3. All advertising materials mentioning features or use of this software
  72.  *    must display the following acknowledgement:
  73.  *    This product includes software developed by the University of
  74.  *    California, Berkeley and its contributors.
  75.  * 4. Neither the name of the University nor the names of its contributors
  76.  *    may be used to endorse or promote products derived from this software
  77.  *    without specific prior written permission.
  78.  *
  79.  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
  80.  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  81.  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  82.  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
  83.  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  84.  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  85.  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  86.  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  87.  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  88.  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  89.  * SUCH DAMAGE.
  90.  *
  91.  *    @(#)ip_icmp.c    7.15 (Berkeley) 4/20/91
  92.  */
  93.  
  94. #include <conf.h>
  95.  
  96. #include <sys/param.h>
  97. #include <sys/systm.h>
  98. #include <sys/malloc.h>
  99. #include <sys/mbuf.h>
  100. #include <sys/protosw.h>
  101. #include <sys/socket.h>
  102. #include <sys/time.h>
  103. #include <sys/kernel.h>
  104.  
  105. #include <net/route.h>
  106. #include <net/if.h>
  107.  
  108. #include <netinet/in.h>
  109. #include <netinet/in_systm.h>
  110. #include <netinet/in_var.h>
  111. #include <netinet/ip.h>
  112. #include <netinet/ip_icmp.h>
  113. #include <netinet/icmp_var.h>
  114.  
  115. #include <netinet/ip_icmp_protos.h>
  116. #include <netinet/ip_input_protos.h>
  117. #include <netinet/ip_output_protos.h>
  118. #include <netinet/in_cksum_protos.h>
  119. #include <netinet/in_protos.h>
  120. #include <kern/uipc_domain_protos.h>
  121. #include <net/raw_usrreq_protos.h>
  122.  
  123. struct    icmpstat icmpstat = { 0 };
  124.  
  125. /*
  126.  * ICMP routines: error generation, receive packet processing, and
  127.  * routines to turnaround packets back to the originator, and
  128.  * host table maintenance routines.
  129.  */
  130. int    icmpprintfs = 0;    /* has effect only if ICMPPRINTFS is defined */
  131.  
  132. extern    struct protosw inetsw[];
  133.  
  134. /*
  135.  * Generate an error packet of type error
  136.  * in response to bad packet ip.
  137.  */
  138.  
  139. void
  140. icmp_error(n, type, code, dest)
  141.     struct mbuf *n;
  142.     int type, code;
  143.     struct in_addr dest;
  144. {
  145.     register struct ip *oip = mtod(n, struct ip *), *nip;
  146.     register unsigned oiplen = oip->ip_hl << 2;
  147.     register struct icmp *icp;
  148.     register struct mbuf *m;
  149.     unsigned icmplen;
  150.  
  151. #ifdef ICMPPRINTFS
  152.     if (icmpprintfs)
  153.         printf("icmp_error(%lx, %ld, %ld)\n", (u_long)oip, type, code);
  154. #endif
  155.     if (type != ICMP_REDIRECT)
  156.         icmpstat.icps_error++;
  157.     /*
  158.      * Don't send error if not the first fragment of message.
  159.      * Don't error if the old packet protocol was ICMP
  160.      * error message, only known informational types.
  161.      */
  162.     if (oip->ip_off &~ (IP_MF|IP_DF))
  163.         goto freeit;
  164.     if (oip->ip_p == IPPROTO_ICMP && type != ICMP_REDIRECT &&
  165.       n->m_len >= oiplen + ICMP_MINLEN &&
  166.       !ICMP_INFOTYPE(((struct icmp *)((caddr_t)oip + oiplen))->icmp_type)) {
  167.         icmpstat.icps_oldicmp++;
  168.         goto freeit;
  169.     }
  170.  
  171.     /*
  172.      * First, formulate icmp message
  173.      */
  174.     m = m_gethdr(M_DONTWAIT, MT_HEADER);
  175.     if (m == NULL)
  176.         goto freeit;
  177.     icmplen = oiplen + min(8, oip->ip_len);
  178.     m->m_len = icmplen + ICMP_MINLEN;
  179.     MH_ALIGN(m, m->m_len);
  180.     icp = mtod(m, struct icmp *);
  181.     if ((u_int)type > ICMP_MAXTYPE)
  182.         panic("icmp_error");
  183.     icmpstat.icps_outhist[type]++;
  184.     icp->icmp_type = type;
  185.     if (type == ICMP_REDIRECT)
  186.         icp->icmp_gwaddr = dest;
  187.     else
  188.         icp->icmp_void = 0;
  189.     if (type == ICMP_PARAMPROB) {
  190.         icp->icmp_pptr = code;
  191.         code = 0;
  192.     }
  193.     icp->icmp_code = code;
  194.     aligned_bcopy((caddr_t)oip, (caddr_t)&icp->icmp_ip, icmplen);
  195.     nip = &icp->icmp_ip;
  196.     nip->ip_len = htons((u_short)(nip->ip_len + oiplen));
  197.  
  198.     /*
  199.      * Now, copy old ip header (without options)
  200.      * in front of icmp message.
  201.      */
  202.     if (m->m_data - sizeof(struct ip) < m->m_pktdat)
  203.         panic("icmp len");
  204.     m->m_data -= sizeof(struct ip);
  205.     m->m_len += sizeof(struct ip);
  206.     m->m_pkthdr.len = m->m_len;
  207.     m->m_pkthdr.rcvif = n->m_pkthdr.rcvif;
  208.     nip = mtod(m, struct ip *);
  209.     aligned_bcopy((caddr_t)oip, (caddr_t)nip, oiplen);
  210.     nip->ip_len = m->m_len;
  211.     nip->ip_hl = sizeof(struct ip) >> 2;
  212.     nip->ip_p = IPPROTO_ICMP;
  213.     icmp_reflect(m);
  214.  
  215. freeit:
  216.     m_freem(n);
  217. }
  218.  
  219. static struct sockproto icmproto = { AF_INET, IPPROTO_ICMP };
  220. static struct sockaddr_in icmpsrc = { sizeof (struct sockaddr_in), AF_INET };
  221. static struct sockaddr_in icmpdst = { sizeof (struct sockaddr_in), AF_INET };
  222. static struct sockaddr_in icmpgw = { sizeof (struct sockaddr_in), AF_INET };
  223. struct sockaddr_in icmpmask = { 8, 0 };
  224. struct in_ifaddr *ifptoia();
  225.  
  226. /*
  227.  * Process a received ICMP message.
  228.  */
  229. void STKARGFUN
  230. icmp_input(m, hlen)
  231.     register struct mbuf *m;
  232.     int hlen;
  233. {
  234.     register struct icmp *icp;
  235.     register struct ip *ip = mtod(m, struct ip *);
  236.     int icmplen = ip->ip_len;
  237.     register int i;
  238.     struct in_ifaddr *ia;
  239.     int code;
  240.     extern u_char ip_protox[];
  241.     extern struct in_addr in_makeaddr();
  242.  
  243.     /*
  244.      * Locate icmp structure in mbuf, and check
  245.      * that not corrupted and of at least minimum length.
  246.      */
  247. #ifdef ICMPPRINTFS
  248.     if (icmpprintfs)
  249.         printf("icmp_input from %lx, len %ld\n", ip->ip_src.s_addr, icmplen);
  250. #endif
  251.     if (icmplen < ICMP_MINLEN) {
  252.         icmpstat.icps_tooshort++;
  253.         goto freeit;
  254.     }
  255.     i = hlen + MIN(icmplen, ICMP_ADVLENMIN);
  256.      if (m->m_len < i && (m = m_pullup(m, i)) == 0)  {
  257.         icmpstat.icps_tooshort++;
  258.         return;
  259.     }
  260.      ip = mtod(m, struct ip *);
  261.     m->m_len -= hlen;
  262.     m->m_data += hlen;
  263.     icp = mtod(m, struct icmp *);
  264.     if (in_cksum(m, icmplen)) {
  265.         icmpstat.icps_checksum++;
  266.         goto freeit;
  267.     }
  268.     m->m_len += hlen;
  269.     m->m_data -= hlen;
  270.  
  271. #ifdef ICMPPRINTFS
  272.     /*
  273.      * Message type specific processing.
  274.      */
  275.     if (icmpprintfs)
  276.         printf("icmp_input, type %ld code %ld\n", icp->icmp_type,
  277.             icp->icmp_code);
  278. #endif
  279.     if (icp->icmp_type > ICMP_MAXTYPE)
  280.         goto raw;
  281.     icmpstat.icps_inhist[icp->icmp_type]++;
  282.     code = icp->icmp_code;
  283.     switch (icp->icmp_type) {
  284.  
  285.     case ICMP_UNREACH:
  286.         if (code > 5)
  287.             goto badcode;
  288.         code += PRC_UNREACH_NET;
  289.         goto deliver;
  290.  
  291.     case ICMP_TIMXCEED:
  292.         if (code > 1)
  293.             goto badcode;
  294.         code += PRC_TIMXCEED_INTRANS;
  295.         goto deliver;
  296.  
  297.     case ICMP_PARAMPROB:
  298.         if (code)
  299.             goto badcode;
  300.         code = PRC_PARAMPROB;
  301.         goto deliver;
  302.  
  303.     case ICMP_SOURCEQUENCH:
  304.         if (code)
  305.             goto badcode;
  306.         code = PRC_QUENCH;
  307.     deliver:
  308.         /*
  309.          * Problem with datagram; advise higher level routines.
  310.          */
  311.         if (icmplen < ICMP_ADVLENMIN || icmplen < ICMP_ADVLEN(icp) ||
  312.             icp->icmp_ip.ip_hl < (sizeof(struct ip) >> 2)) {
  313.             icmpstat.icps_badlen++;
  314.             goto freeit;
  315.         }
  316.         NTOHS(icp->icmp_ip.ip_len);
  317. #ifdef ICMPPRINTFS
  318.         if (icmpprintfs)
  319.             printf("deliver to protocol %ld\n", icp->icmp_ip.ip_p);
  320. #endif
  321.         icmpsrc.sin_addr = icp->icmp_ip.ip_dst;
  322.         if (inetsw[ip_protox[icp->icmp_ip.ip_p]].pr_ctlinput)
  323.             (*inetsw[ip_protox[icp->icmp_ip.ip_p]].pr_ctlinput)
  324.               (code, (struct sockaddr *)&icmpsrc,
  325.                (caddr_t) &icp->icmp_ip);
  326.         break;
  327.  
  328.     badcode:
  329.         icmpstat.icps_badcode++;
  330.         break;
  331.  
  332.     case ICMP_ECHO:
  333.         icp->icmp_type = ICMP_ECHOREPLY;
  334.         goto reflect;
  335.  
  336.     case ICMP_TSTAMP:
  337.         if (icmplen < ICMP_TSLEN) {
  338.             icmpstat.icps_badlen++;
  339.             break;
  340.         }
  341.         icp->icmp_type = ICMP_TSTAMPREPLY;
  342.         icp->icmp_rtime = iptime();
  343.         icp->icmp_ttime = icp->icmp_rtime;    /* bogus, do later! */
  344.         goto reflect;
  345.         
  346.     case ICMP_IREQ:
  347. #define    satosin(sa)    ((struct sockaddr_in *)(sa))
  348.         if (in_netof(ip->ip_src) == 0 &&
  349.             (ia = ifptoia(m->m_pkthdr.rcvif)))
  350.             ip->ip_src = in_makeaddr(in_netof(IA_SIN(ia)->sin_addr),
  351.                 in_lnaof(ip->ip_src));
  352.         icp->icmp_type = ICMP_IREQREPLY;
  353.         goto reflect;
  354.  
  355.     case ICMP_MASKREQ:
  356.         if (icmplen < ICMP_MASKLEN ||
  357.             (ia = ifptoia(m->m_pkthdr.rcvif)) == 0)
  358.             break;
  359.         icp->icmp_type = ICMP_MASKREPLY;
  360.         icp->icmp_mask = ia->ia_sockmask.sin_addr.s_addr;
  361.         if (ip->ip_src.s_addr == 0) {
  362.             if (ia->ia_ifp->if_flags & IFF_BROADCAST)
  363.                 ip->ip_src = satosin(&ia->ia_broadaddr)->sin_addr;
  364.             else if (ia->ia_ifp->if_flags & IFF_POINTOPOINT)
  365.                 ip->ip_src = satosin(&ia->ia_dstaddr)->sin_addr;
  366.         }
  367. reflect:
  368.         ip->ip_len += hlen;    /* since ip_input deducts this */
  369.         icmpstat.icps_reflect++;
  370.         icmpstat.icps_outhist[icp->icmp_type]++;
  371.         icmp_reflect(m);
  372.         return;
  373.  
  374.     case ICMP_REDIRECT:
  375.         if (icmplen < ICMP_ADVLENMIN || icmplen < ICMP_ADVLEN(icp)) {
  376.             icmpstat.icps_badlen++;
  377.             break;
  378.         }
  379.         /*
  380.          * Short circuit routing redirects to force
  381.          * immediate change in the kernel's routing
  382.          * tables.  The message is also handed to anyone
  383.          * listening on a raw socket (e.g. the routing
  384.          * daemon for use in updating its tables).
  385.          */
  386.         icmpgw.sin_addr = ip->ip_src;
  387.         icmpdst.sin_addr = icp->icmp_gwaddr;
  388. #ifdef    ICMPPRINTFS
  389.         if (icmpprintfs)
  390.             printf("redirect dst %lx to %lx\n", icp->icmp_ip.ip_dst.s_addr,
  391.                 icp->icmp_gwaddr.s_addr);
  392. #endif
  393.         if (code == ICMP_REDIRECT_NET || code == ICMP_REDIRECT_TOSNET) {
  394.             u_long in_netof();
  395.             icmpsrc.sin_addr =
  396.              in_makeaddr(in_netof(icp->icmp_ip.ip_dst), INADDR_ANY);
  397.             in_sockmaskof(icp->icmp_ip.ip_dst, &icmpmask);
  398.             rtredirect((struct sockaddr *)&icmpsrc,
  399.               (struct sockaddr *)&icmpdst,
  400.               (struct sockaddr *)&icmpmask, RTF_GATEWAY,
  401.               (struct sockaddr *)&icmpgw, (struct rtentry **)0);
  402.             icmpsrc.sin_addr = icp->icmp_ip.ip_dst;
  403.             pfctlinput(PRC_REDIRECT_NET,
  404.               (struct sockaddr *)&icmpsrc);
  405.         } else {
  406.             icmpsrc.sin_addr = icp->icmp_ip.ip_dst;
  407.             rtredirect((struct sockaddr *)&icmpsrc,
  408.               (struct sockaddr *)&icmpdst,
  409.               (struct sockaddr *)0, RTF_GATEWAY | RTF_HOST,
  410.               (struct sockaddr *)&icmpgw, (struct rtentry **)0);
  411.             pfctlinput(PRC_REDIRECT_HOST,
  412.               (struct sockaddr *)&icmpsrc);
  413.         }
  414.         break;
  415.  
  416.     /*
  417.      * No kernel processing for the following;
  418.      * just fall through to send to raw listener.
  419.      */
  420.     case ICMP_ECHOREPLY:
  421.     case ICMP_TSTAMPREPLY:
  422.     case ICMP_IREQREPLY:
  423.     case ICMP_MASKREPLY:
  424.     default:
  425.         break;
  426.     }
  427.  
  428. raw:
  429.     icmpsrc.sin_addr = ip->ip_src;
  430.     icmpdst.sin_addr = ip->ip_dst;
  431.     (void) raw_input(m, &icmproto, (struct sockaddr *)&icmpsrc,
  432.         (struct sockaddr *)&icmpdst);
  433.     return;
  434.  
  435. freeit:
  436.     m_freem(m);
  437. }
  438.  
  439. /*
  440.  * Reflect the ip packet back to the source
  441.  */
  442. void
  443. icmp_reflect(m)
  444.     struct mbuf *m;
  445. {
  446.     register struct ip *ip = mtod(m, struct ip *);
  447.     register struct in_ifaddr *ia;
  448.     struct in_addr t;
  449.     struct mbuf *opts = 0;
  450.     int optlen = (ip->ip_hl << 2) - sizeof(struct ip);
  451.  
  452.     t = ip->ip_dst;
  453.     ip->ip_dst = ip->ip_src;
  454.     /*
  455.      * If the incoming packet was addressed directly to us,
  456.      * use dst as the src for the reply.  Otherwise (broadcast
  457.      * or anonymous), use the address which corresponds
  458.      * to the incoming interface.
  459.      */
  460.     for (ia = in_ifaddr; ia; ia = ia->ia_next) {
  461.         if (t.s_addr == IA_SIN(ia)->sin_addr.s_addr)
  462.             break;
  463.         if ((ia->ia_ifp->if_flags & IFF_BROADCAST) &&
  464.             t.s_addr == satosin(&ia->ia_broadaddr)->sin_addr.s_addr)
  465.             break;
  466.     }
  467.     if (ia == (struct in_ifaddr *)0)
  468.         ia = ifptoia(m->m_pkthdr.rcvif);
  469.     if (ia == (struct in_ifaddr *)0)
  470.         ia = in_ifaddr;
  471.     t = IA_SIN(ia)->sin_addr;
  472.     ip->ip_src = t;
  473.     ip->ip_ttl = MAXTTL;
  474.  
  475.     if (optlen > 0) {
  476.         register u_char *cp;
  477.         int opt, cnt;
  478.         u_int len;
  479.  
  480.         /*
  481.          * Retrieve any source routing from the incoming packet;
  482.          * add on any record-route or timestamp options.
  483.          */
  484.         cp = (u_char *) (ip + 1);
  485.         if ((opts = ip_srcroute()) == 0 &&
  486.             (opts = m_gethdr(M_DONTWAIT, MT_HEADER))) {
  487.             opts->m_len = sizeof(struct in_addr);
  488.             mtod(opts, struct in_addr *)->s_addr = 0;
  489.         }
  490.         if (opts) {
  491. #ifdef ICMPPRINTFS
  492.             if (icmpprintfs)
  493.                 printf("icmp_reflect optlen %ld rt %ld => ",
  494.                 optlen, opts->m_len);
  495. #endif
  496.             for (cnt = optlen; cnt > 0; cnt -= len, cp += len) {
  497.                 opt = cp[IPOPT_OPTVAL];
  498.                 if (opt == IPOPT_EOL)
  499.                     break;
  500.                 if (opt == IPOPT_NOP)
  501.                     len = 1;
  502.                 else {
  503.                     len = cp[IPOPT_OLEN];
  504.                     if (len <= 0 || len > cnt)
  505.                         break;
  506.                 }
  507.                 /*
  508.                  * should check for overflow, but it "can't happen"
  509.                  */
  510.                 if (opt == IPOPT_RR || opt == IPOPT_TS) {
  511.                     bcopy((caddr_t)cp,
  512.                     mtod(opts, caddr_t) + opts->m_len, len);
  513.                     opts->m_len += len;
  514.                 }
  515.             }
  516.             if (opts->m_len % 4 != 0) {
  517.                 *(mtod(opts, caddr_t) + opts->m_len) = IPOPT_EOL;
  518.                 opts->m_len++;
  519.             }
  520. #ifdef ICMPPRINTFS
  521.             if (icmpprintfs)
  522.                 printf("%ld\n", opts->m_len);
  523. #endif
  524.         }
  525.         /*
  526.          * Now strip out original options by copying rest of first
  527.          * mbuf's data back, and adjust the IP length.
  528.          */
  529.         ip->ip_len -= optlen;
  530.         ip->ip_hl = sizeof(struct ip) >> 2;
  531.         m->m_len -= optlen;
  532.         if (m->m_flags & M_PKTHDR)
  533.             m->m_pkthdr.len -= optlen;
  534.         optlen += sizeof(struct ip);
  535.         bcopy((caddr_t)ip + optlen, (caddr_t)(ip + 1),
  536.              (unsigned)(m->m_len - sizeof(struct ip)));
  537.     }
  538.     icmp_send(m, opts);
  539.     if (opts)
  540.         (void)m_free(opts);
  541. }
  542.  
  543. struct in_ifaddr *
  544. ifptoia(ifp)
  545.     struct ifnet *ifp;
  546. {
  547.     register struct in_ifaddr *ia;
  548.  
  549.     for (ia = in_ifaddr; ia; ia = ia->ia_next)
  550.         if (ia->ia_ifp == ifp)
  551.             return (ia);
  552.     return ((struct in_ifaddr *)0);
  553. }
  554.  
  555. /*
  556.  * Send an icmp packet back to the ip level,
  557.  * after supplying a checksum.
  558.  */
  559. void
  560. icmp_send(m, opts)
  561.     register struct mbuf *m;
  562.     struct mbuf *opts;
  563. {
  564.     register struct ip *ip = mtod(m, struct ip *);
  565.     register int hlen;
  566.     register struct icmp *icp;
  567.  
  568.     hlen = ip->ip_hl << 2;
  569.     m->m_data += hlen;
  570.     m->m_len -= hlen;
  571.     icp = mtod(m, struct icmp *);
  572.     icp->icmp_cksum = 0;
  573.     icp->icmp_cksum = in_cksum(m, ip->ip_len - hlen);
  574.     m->m_data -= hlen;
  575.     m->m_len += hlen;
  576. #ifdef ICMPPRINTFS
  577.     if (icmpprintfs)
  578.         printf("icmp_send dst %lx src %lx\n", ip->ip_dst.s_addr, ip->ip_src.s_addr);
  579. #endif
  580.     (void) ip_output(m, opts, (struct route *)0, 0);
  581. }
  582.  
  583. n_time
  584. iptime()
  585. {
  586.     struct timeval atv;
  587.     u_long t;
  588.  
  589.     microtime(&atv);
  590.     t = (atv.tv_sec % (24*60*60)) * 1000 + atv.tv_usec / 1000;
  591.     return (htonl(t));
  592. }
  593.